module baremetal.tls;

version(FreeStanding){}else{
    static assert(0,"not ");
}

private{
    import baremetal;
    import baremetal.stdlib;

    //__gshared extern(C) extern void* tlsptr;
    //__gshared extern(C) extern void* __tdata_start__;
    extern(C) extern __gshared size_t __tlsptr;

}



extern(C) 
void* __aeabi_read_tp() //nothrow @nounwind @nogc 
{
    import ldc.llvmasm;
    /*
        cortex-m4 单处理器
        单线程工作,无tls动作,直接返回sram地址段
    */
    /*
    return __asm!(void*)(`ldr R0,=tlsptr
                        ldr R0,[R0]`,"=r");
    */
    /*
    return __asm!(void*)(`ldr R0,=$1
                        ldr R0,[R0]`,"=r,i",&tlsptr);
    */
    // 未对多线程进行处理
    // 未实tls,直接返回tdata数据段地址
    //return tlsptr;
    /*
    return __asm!(void*)(`ldr R0,=$1
                            ldr R0,[R0]`,"=r,i",&tlsptr);
                            
                            */
    //return &tlsptr;
    return &(__tlsptr);

}

/*
// 初始化tls
pragma(crt_constructor)
static this() @system 
{
    //size_t size = (cast(size_t)&__tdata_size__) + (cast(size_t)&__tbss_size__);
    
    //tlsptr = alloca(size);

    /// 初始化TLS内存
    //memset(cast(ubyte*)&tlsptr,0x00,size + 8);
    /// 复制tdata section .tdata
    //memcpy(cast(ubyte*)&tlsptr,cast(ubyte*)&__tdata_start__,cast(size_t)&__tdata_size__);  

}
*/

private{
    
    extern(C) 
    {
        //extern __gshared void* __tdata_start__,__tdata_end__,__stdata_loadaddr__;

        //extern __gshared void* __tdata_size__,__tbss_size__;

        //extern __gshared void* __tbss_start__;

        /// tdata
        extern __gshared void* __stdata_loadaddr__;
        extern __gshared size_t __tdata_start__,__tdata_size__,__tdata_end__;
        /// tbss 段
        extern __gshared size_t __tbss_start__,__tbss_size__,__tbss_end__;
    }
    
	pragma(LDC_no_typeinfo)
	{
		struct TlsLinkerParams
		{
			void* data;
			size_t dataSize;
			void* bss;
			size_t bssSize; 
			size_t fullSize;
		}
	}
	/// Get TLS data defined in linker script
	TlsLinkerParams getTlsLinkerParams() nothrow @nogc 
	{
		TlsLinkerParams param;
		param.data = cast(void*)&__stdata_loadaddr__;
		param.dataSize = cast(size_t)&__tdata_size__;
		param.bss = cast(void*)&__tbss_start__;
		param.bssSize = cast(size_t)&__tbss_size__;
		param.fullSize = param.dataSize + param.bssSize;
		return param;
	}

    enum ARM_EABI_TCB_SIZE = 8;
}

enum tlsPointerIndex = 0;